package com.jinyi.wwdeng.autodialer.manager

import android.content.Context
import android.util.Log
import com.jinyi.wwdeng.autodialer.MyApplication
import com.jinyi.wwdeng.autodialer.data.CallTask
import com.jinyi.wwdeng.autodialer.http.HttpApi
import com.jinyi.wwdeng.autodialer.http.HttpUtil
import com.jinyi.wwdeng.autodialer.repository.CallTaskRepository
import com.jinyi.wwdeng.autodialer.utils.AppConfig
import com.jinyi.wwdeng.autodialer.utils.AppException
import com.jinyi.wwdeng.autodialer.utils.CallLogUtil
import com.jinyi.wwdeng.autodialer.utils.CallRecorderUtil
import com.jinyi.wwdeng.autodialer.utils.ServiceConfig
import com.jinyi.wwdeng.autodialer.utils.event.EventAction
import com.jinyi.wwdeng.autodialer.utils.event.EventAction.ACTION_UPDATE_DIAL
import com.jinyi.wwdeng.autodialer.utils.event.EventAction.ACTION_UPDATE_TOAST
import com.jinyi.wwdeng.autodialer.utils.event.EventAction.EXTRA_MESSAGE
import com.jinyi.wwdeng.autodialer.utils.event.EventAction.EXTRA_PHONE_NUMBER
import com.jinyi.wwdeng.autodialer.utils.event.EventAction.EXTRA_STATUS
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.json.JSONObject
import java.util.concurrent.atomic.AtomicReference

/**
 * 通话管理器
 */
class CallTaskManager(
    private val context: Context,
    private val taskRepository: CallTaskRepository,
    private val config: ServiceConfig
) {
    private final val TAG = "CallTaskManager"
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())

    private val currentDialingTask = AtomicReference<CallTask?>(null)

    suspend fun handleDialScheduling() {
        try {
            // 检查是否正在拨号中
            if (isDialing()) {
                Log.d(TAG, "已有任务正在拨号中，跳过")
                return
            }

            // 获取单个待拨号任务
            val pendingTasks = taskRepository.getPendingTasks(1)
            if (pendingTasks.isEmpty()) {
                Log.d(TAG, "数据库没有待拨号数据，从api获取")
                // 从接口获取新号码
                fetchNewNumber()
            } else {
                pendingTasks.firstOrNull()?.let { task ->
                    startDialing(task)
                }
            }
        } catch (e: AppException.DatabaseException) {
            Log.e(TAG, "数据库操作失败", e)
        } catch (e: Exception) {
            Log.e(TAG, "拨号调度失败", e)
        }
    }

    private suspend fun fetchNewNumber() {
        try {
            val task = fetchNumbersFromApi()
            if (task != null){
                val taskId = taskRepository.insertTask(task)
                task.id = taskId
                Log.d(TAG, "获取新号码: ${task.phoneNumber}, 任务ID: $taskId")
                startDialing(task)
            }
        } catch (e: AppException.NoAvailableNumberException) {
            Log.w(TAG, "没有可用的电话号码")
        } catch (e: AppException.NetworkException) {
            Log.e(TAG, "获取号码API调用失败", e)
        } catch (e: AppException.TimeoutException){
            Log.e(TAG, "连接超时", e)
        }
    }

    private fun startDialing(task: CallTask) {
        currentDialingTask.set(task)
        // 更新数据库状态
        scope.launch {
            task.status = CallTask.CallStatus.DIAL_DIALING
            task.callStartTime = System.currentTimeMillis()
            taskRepository.updateTask(task.copy(status = CallTask.CallStatus.DIAL_DIALING, callStartTime = System.currentTimeMillis()))
            //更新通话状态
            EventAction.sendBroadcast(
                ACTION_UPDATE_DIAL,
                EXTRA_PHONE_NUMBER to task.phoneNumber,
                EXTRA_STATUS to task.status.name,
            )
        }
        Log.d(TAG, "开始拨号: ${task.phoneNumber}")
        executeDial(task)
    }

    /* 开始拨号 */
    private fun executeDial(task: CallTask) {
        try {
            DialerManager.getInstance(context).dialNumberV2(task)
        } catch (e: SecurityException) {
            throw AppException.CallPermissionException("")
        }
    }

    /* 通话已接通 */
    fun onCallAnswered() {
        currentDialingTask.get()?.let { task ->
            Log.d(TAG, "电话接通: ${task.phoneNumber}")
            //开始录音
            CallRecorderUtil.startRecording(context,task.phoneNumber)
        }
    }

    /* 通话已挂断 */
    fun onCallEnded() {
        //非通话中，不执行停止录音
        if (!isDialing()) {
            return
        }
        //通话结束，停止录音
        CallRecorderUtil.stopRecording { audioPath ->
            currentDialingTask.get()?.let { task ->
                scope.launch {
                    //延时500毫秒查询记录，避免通话记录数据库未更新
                    delay(500)
                    val callLog = CallLogUtil.read(MyApplication.instance, task.phoneNumber)
                    Log.e("TAG",">>>>>${task.phoneNumber} log >>>>>>>>>>>>>>>>>>>>>${callLog}")

                    audioPath?.let { path ->
                        task.status = CallTask.CallStatus.UPLOAD_PENDING
                        task.callEndTime = System.currentTimeMillis()
                        task.localAudioPath = path
                        task.callLog = callLog
                        //更新状态为成功，更新结束通话时间，更新录音文件本地路径，更新通话记录信息
                        taskRepository.updateTask(task.copy(status = CallTask.CallStatus.UPLOAD_PENDING, callEndTime = System.currentTimeMillis(), localAudioPath = path, callLog = callLog))
                        //更新通话状态
                        EventAction.sendBroadcast(
                            ACTION_UPDATE_DIAL,
                            EXTRA_PHONE_NUMBER to task.phoneNumber,
                            EXTRA_STATUS to task.status.name,
                        )
                        Log.d(TAG, "任务 ${task.id} 更新为待上传状态")
                    } ?: run {
                        task.status = CallTask.CallStatus.DIAL_FAILED
                        task.callEndTime = System.currentTimeMillis()
                        task.callLog = callLog
                        task.errorMessage = "录音文件为空"
                        taskRepository.updateTask(task.copy(status = CallTask.CallStatus.DIAL_FAILED, callEndTime = System.currentTimeMillis(), callLog = callLog, errorMessage = "录音文件为空"))
                        //更新通话状态
                        EventAction.sendBroadcast(
                            ACTION_UPDATE_DIAL,
                            EXTRA_PHONE_NUMBER to task.phoneNumber,
                            EXTRA_STATUS to task.status.name,
                        )
                    }
                }
                currentDialingTask.set(null)
            }
        }
    }

    fun onDialTimeout() {
        currentDialingTask.get()?.let { task ->
            Log.w(TAG, "拨号超时: ${task.phoneNumber}")
            scope.launch {
                task.status = CallTask.CallStatus.DIAL_FAILED
                task.callEndTime = System.currentTimeMillis()
                task.errorMessage = "拨号超时"
                taskRepository.updateTaskStatusWithError(task.id, CallTask.CallStatus.DIAL_FAILED, "拨号超时")
            }
            currentDialingTask.set(null)
        }
    }

    fun isDialing(): Boolean = currentDialingTask.get() != null

    private suspend fun fetchNumbersFromApi(): CallTask? {
        try {
            val body = JSONObject().apply {
                put("sysLoginName", AppConfig.userName)
                put("token",AppConfig.userToken)
            }
            val data  = HttpUtil.getInstance().postJsonSuspend(context, HttpApi.API_GET_NUMBER,body.toString(),null)
            val code = data.optInt("code")
            if (code != 0){
                //通知拨号管理器错误
                EventAction.sendBroadcast(
                    ACTION_UPDATE_TOAST,
                    EXTRA_STATUS to "error",
                            EXTRA_MESSAGE to "${data.optString("msg")}",
                )
                throw AppException.NetworkException(HttpApi.API_GET_NUMBER,code)
            }
            val dataObj = data.optJSONObject("obj")
            if (dataObj == null){
                throw AppException.NetworkException(HttpApi.API_GET_NUMBER,code)
            }
            val number = dataObj.optString("mobile","")
            if (number.isEmpty()){
                //更新通话状态
                EventAction.sendBroadcast(
                    ACTION_UPDATE_DIAL,
                    EXTRA_STATUS to "空闲中",
                )
                return null
            }
            return CallTask(phoneNumber = number, product = dataObj.optString("product"), orderId = dataObj.optString("orderId"), mobileType = dataObj.optString("mobileType"), userId = dataObj.optString("userId"))
        } catch (e: Exception){
            throw AppException.TimeoutException(HttpApi.API_GET_NUMBER)
        }
    }

    // 关闭协程作用域
    fun shutdown() {
        scope.cancel()
    }
}